package com.pi.config;

import com.pi.core.security.SpringDataTokenRepositoryImpl;
import com.pi.framework.security.util.PermissionSecurityCheck;
import com.pi.sys.service.MenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import java.util.*;

@Configuration
@ConditionalOnProperty(name = "security.oauth2.enabled", havingValue = "false", matchIfMissing = true)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	private static final String[] URLS = { "/*.html", "/static/**", "/**/*.html", "/**/*.css", "/**/*.js", "/**/*.jpg",
			"/**/*.png", "/favicon.ico", "/**/font/**", "/swagger-resources/**", "/webjars/**", "/**/api-docs/**",
			"/login/**", "/logout/**","/api/**", "/WebApi/**" };

	@Value("${security.jwt.route.authentication.login:/auth}")
	private String authUrl;

	/**
	@Value("${spring.ldap.group-search-base}")
	private String groupSearchBase = "";

	@Value("${spring.ldap.password}")
	private String ldapPassword = "";

	@Value("${spring.ldap.urls}")
	private String ldapUrl = "";

	@Value("${spring.ldap.username}")
	private String ldapUsername = "";

	@Value("${spring.ldap.user-dn-patterns}")
	private String userDnPatterns = "";

	@Value("${spring.ldap.user-search-base}")
	private String userSearchBase = "";

	@Value("${spring.ldap.user-search-filter}")
	private String userSearchFilter = "";
	**/

	@Value("${security.jwt.route.authentication.logout}")
	private String logoutUrl;

	@Value("${security.url.permitAll}")
	private String permitAllUrl;

	@Autowired
	private UserDetailsService userDetailsService;

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		// @formatter:off
		Set<String> defaultUrls = new HashSet<String>();
		defaultUrls.addAll(Arrays.asList(URLS));
		if (permitAllUrl != null && !StringUtils.isBlank(permitAllUrl)) {
			defaultUrls.addAll(Arrays.asList(permitAllUrl.split(",")));
		}
		HttpSecurity and = httpSecurity.headers()
				// TODO: (REWRITE) This enables opening javamelody in an
				// iframe, see https://jira.spring.io/browse/SEC-2501
				// and https://jira.spring.io/browse/SPR-11496
				.frameOptions().sameOrigin()
				//.frameOptions().disable()
				.and().sessionManagement().sessionFixation().migrateSession()
				.and().authorizeRequests()
				// allow anonymous resource requests
				.antMatchers(defaultUrls.toArray(new String[0])).permitAll()
				// .antMatchers("/admin/**").hasRole("Administrators")
				// .antMatchers("/druid/**").authenticated()
				// index page
				.antMatchers("/").permitAll()
				// api
				//.antMatchers("/api/**").authenticated()
				// app
				.antMatchers("/app/**").authenticated()
				// profile
				.antMatchers("/profile/**").authenticated()
				// dashboard
				.antMatchers("/dashboard/**").authenticated()
				//
				.antMatchers("/api/**").permitAll()
				// front supplier's users.
				.antMatchers("/suppl/**").access("authenticated and principal.front")
				// others
				.antMatchers("/**").access("authenticated and !principal.front")
				// permission check
				.antMatchers("/**").access("@securityCheck.check(authentication,request)")
				// .accessDecisionManager(accessDecisionManager)
				// all should be authenticated
				.anyRequest().authenticated()
				// .anyRequest().access("not authentication.principal.front")
				// Form login
				.and().formLogin().loginPage("/login").permitAll().usernameParameter("username")
				.passwordParameter("password").failureUrl("/login/fail").defaultSuccessUrl("/login/success")
				// Logout
				.and().logout().invalidateHttpSession(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
				.logoutSuccessUrl("/logout/success")
				// Remember me
				// .and().rememberMe().tokenRepository(springDataTokenRepository()).useSecureCookie(true)

				// .addFilterBefore(roleAccessFilter(),
				// org.springframework.security.web.access.intercept.FilterSecurityInterceptor.class)
				// Exception handler
				.and()
				.exceptionHandling().accessDeniedPage("/403").and();
		// CSRF
		defaultUrls.add("/druid/**");
		and.csrf().ignoringAntMatchers(defaultUrls.toArray(new String[0]))
				.csrfTokenRepository(new HttpSessionCsrfTokenRepository());

		/**
        httpSecurity.headers().addHeaderWriter(new XFrameOptionsHeaderWriter(
                new WhiteListedAllowFromStrategy(
                        Arrays.asList("http://www.baidu.com", "http://baidu.com",
                                "https://localhsot:9060"))));
**/

    }

	@Autowired
	public void configureAuthentication(AuthenticationManagerBuilder builder) throws Exception {
		builder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
		// builder.ldapAuthentication().userDnPatterns(userDnPatterns).groupSearchBase(groupSearchBase)
		// .userSearchBase(userSearchBase).userSearchFilter(userSearchFilter)
		// .ldapAuthoritiesPopulator(ldapAuthoritiesPopulator()).rolePrefix("").contextSource().url(ldapUrl)
		// .managerDn(ldapUsername).managerPassword(ldapPassword);
		// .and().passwordCompare();
		// .passwordEncoder(new
		// LdapShaPasswordEncoder()).passwordAttribute("userPassword");
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	public PermissionSecurityCheck securityCheck(MenuService menuService) {
		return new PermissionSecurityCheck(menuService);
	}

	@Bean
	public SpringDataTokenRepositoryImpl springDataTokenRepository() {
		SpringDataTokenRepositoryImpl springDataTokenRepository = new SpringDataTokenRepositoryImpl();
		return springDataTokenRepository;
	}


}